package com.zff.rental.service.user;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import com.zff.rental.common.BusinessException;
import com.zff.rental.common.PageVo;
import com.zff.rental.common.ResultCode;
import com.zff.rental.entity.user.UserEntity;
import com.zff.rental.mapstruct.user.UserMapstruct;
import com.zff.rental.service.BaseService;
import com.zff.rental.tools.UserContextHolder;
import com.zff.rental.utils.specification.SpecBuilder;
import com.zff.rental.vo.user.*;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author HCY
 */
@Service
public class UserServer extends BaseService {

    public UserVo add(AddUserParams params) {
        if (!adminService.isAdmin()) {
            throw new BusinessException("权限不足");
        }

        UserEntity userEntity = UserMapstruct.INSTANCE.map(params);
        addSaltPassword(userEntity, params.getPassword());

        if (StringUtils.hasText(userEntity.getAccountName()) && userRepository.existsByAccountName(userEntity.getAccountName())) {
            throw new BusinessException("账号已存在");
        }
        if (StringUtils.hasText(userEntity.getPhone()) && userRepository.existsByPhone(userEntity.getPhone())) {
            throw new BusinessException("手机号已存在");
        }
        if (StringUtils.hasText(userEntity.getEmail()) && userRepository.existsByEmail(userEntity.getEmail())) {
            throw new BusinessException("电子邮箱已存在");
        }

        UserEntity saveResult = userRepository.save(userEntity);
        return UserMapstruct.INSTANCE.map(saveResult);
    }

    public UserVo modify(ModifyUserParams params) {
        if (!adminService.isAdmin()) {
            if (!Objects.equals(UserContextHolder.getUserId(), params.getUserId())) {
                throw new BusinessException("非管理员只能修改自己的信息");
            }
        }

        UserEntity findResult = userRepository.findById(params.getUserId()).orElseThrow(ResultCode.RECORD_NOT_EXISTS::toException);
        UserMapstruct.INSTANCE.merge(findResult, params);
        if (params.getPassword() != null) {
            addSaltPassword(findResult, params.getPassword());
        }
        UserEntity saveResult = userRepository.save(findResult);
        return UserMapstruct.INSTANCE.map(saveResult);
    }

    public UserVo details(Long userId) {
        UserEntity findResult = userRepository.findById(userId).orElseThrow(ResultCode.RECORD_NOT_EXISTS::toException);

        return UserMapstruct.INSTANCE.map(findResult);
    }

    /**
     * 对用户传入的密码进行加盐处理
     */
    public static void addSaltPassword(UserEntity userEntity, String password) {
        if (!StringUtils.hasText(password)) {
            return;
        }

        String salt = RandomUtil.randomString(32);
        String saltPassword = SecureUtil.md5(password + salt);
        userEntity.setSalt(salt);
        userEntity.setPassword(saltPassword);
    }

    /**
     * 登录
     */
    public UserEntity login(LoginParams loginParams) {
        Optional<UserEntity> userOptional = userRepository.findOneByPhone(loginParams.getPhone());
        if (userOptional.isEmpty()) {
            throw new BusinessException("用户不存在");
        }

        UserEntity userEntity = userOptional.get();

        String saltPassword = SecureUtil.md5(loginParams.getPassword() + userEntity.getSalt());
        if (!Objects.equals(saltPassword, userEntity.getPassword())) {
            throw new BusinessException("密码错误");
        }
        if (userEntity.getDisabled() != null && userEntity.getDisabled() == 1) {
            throw new BusinessException("账号已禁用，请联系管理员");
        }
        if (Objects.equals(userEntity.getDel(), userEntity.getUserId())) {
            throw new BusinessException("账号已被删除，请联系管理员恢复");
        }
        return userEntity;
    }

    public UserEntity refreshToken() {
        Long userId = UserContextHolder.getUserId();
        return userRepository.findById(userId).orElseThrow(() -> new BusinessException("用户不存在"));
    }

    public List<UserVo> allList() {
        List<UserEntity> all;
        if (adminService.isAdmin()) {
            all = userRepository.findAll();
        } else {
            all = userRepository.findById(UserContextHolder.getUserId())
                    .map(Collections::singletonList).orElse(Collections.emptyList());
        }

        return UserMapstruct.INSTANCE.mapAsList(all);
    }

    public PageVo<UserVo> list(UserListParams params) {
        Specification<UserEntity> where = SpecBuilder.<UserEntity>builder()
                .likeAll("nickname", params.getNickname())
                .likeAll("phone", params.getPhone())
                .add(params.isIgnore(), params.toSpecification())
                .buildAnd();

        Page<UserEntity> findResult = userRepository.findAll(where, params.generatePageable());

        List<UserEntity> records = findResult.getContent();
        List<UserVo> voList = UserMapstruct.INSTANCE.mapAsList(records);

        return PageVo.of(findResult, voList);
    }

    public Boolean resetPassword(ResetPasswordParams params) {
        if (!adminService.isAdmin()) {
            if (!Objects.equals(UserContextHolder.getUserId(), params.getUserId())) {
                throw new BusinessException("非管理员只能修改自己的信息");
            }
        }
        UserEntity userEntity = userRepository.findById(params.getUserId())
                .orElseThrow(ResultCode.RECORD_NOT_EXISTS::toException);
        addSaltPassword(userEntity, params.getNewPassword());
        userRepository.save(userEntity);
        return true;
    }
}
